import { Injectable, Inject } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';
import { share } from 'rxjs/operators';

import { STORE_TOKEN, IToken, ITokenService, IStore } from '../auth.interface';
import { AuthConfig } from '../../config/auth.config';

@Injectable()
export class TokenService implements ITokenService {

  private change$: BehaviorSubject<IToken> = new BehaviorSubject<IToken>(null);

  constructor(
    private options: AuthConfig,
    @Inject(STORE_TOKEN) private store: IStore,
  ) { }

  private _redirect: string;

  get login_url(): string {
    return this.options.login_url;
  }

  get redirect(): string {
    return this._redirect || '/';
  }

  set redirect(val: string) {
    this._redirect = val;
  }

  set(data: IToken): boolean {
    this.change$.next(data);
    return this.store.set(this.options.store_key, data, {
      expires: this.options.token_exp_offset,
      domain: this.options.token_domain,
      path: this.options.token_path
    });
  }

  get(type?: any);
  get<T extends IToken>(type?: { new(): T }): T {
    const data = this.store.get(this.options.store_key);
    return type ? (Object.assign(new type(), data) as T) : (data as T);
  }

  clear(): void {
    this.change$.next(null);
    this.store.remove(this.options.store_key, {
      expires: this.options.token_exp_offset,
      domain: this.options.token_domain,
      path: this.options.token_path
    });
  }

  change(): Observable<IToken> {
    return this.change$.pipe(share());
  }
}
